#include "string.h"
#include "common_def.h"
#include "osal_debug.h"
#include "osal_task.h"
#include "cmsis_os2.h"
#include "securec.h"
#include "sle_device_discovery.h"
#include "sle_connection_manager.h"
#include "sle_ssap_client.h"
#include "sle_uart_client.h"
#include "sle_errcode.h"
#include "ohos_init.h"
#include "ohos_sle_common.h"
#include "ohos_sle_errcode.h"
#include "ohos_sle_ssap_server.h"
#include "ohos_sle_ssap_client.h"
#include "ohos_sle_device_discovery.h"
#include "ohos_sle_connection_manager.h"
#include "iot_uart.h"
#include "pinctrl.h"
#include "uart.h"
#include "errcode.h"
#include <string.h>    // 字符串处理(操作字符数组)

#include "wifi_connecter.h" // easy wifi (station模式)
#include "mqtt.h"      // MQTT接口

// #include <stdio.h>
// #include <string.h>

// *****************星闪部分
#define SLE_MTU_SIZE_DEFAULT 512
#define SLE_SEEK_INTERVAL_DEFAULT 100
#define SLE_SEEK_WINDOW_DEFAULT 100
#define UUID_16BIT_LEN 2
#define UUID_128BIT_LEN 16
#define SLE_UART_TASK_DELAY_MS 1000
#define SLE_UART_WAIT_SLE_CORE_READY_MS 5000
#ifndef SLE_UART_SERVER_NAME
#define SLE_UART_SERVER_NAME "208"
#endif
#define SLE_UART_CLIENT_LOG "[sle uart client]"
#define UUID_LEN_2     2
#define device_my 5
static char g_sle_uuid_app_uuid[] = { 0x39, 0xBE, 0xA8, 0x80, 0xFC, 0x70, 0x11, 0xEA, \
    0xB7, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static unsigned char uartReadBuff[100];
static ssapc_find_service_result_t g_sle_uart_find_service_result = { 0 };
static sle_announce_seek_callbacks_t g_sle_uart_seek_cbk = { 0 };
static SleConnectionCallbacks g_sle_uart_connect_cbk = { 0 };
static ssapc_callbacks_t g_sle_uart_ssapc_cbk = { 0 };
static SleAddr g_sle_uart_remote_addr = { 0 };
static SleAddr device_addr_my[device_my] = { 
    {.type = 0, .addr = {0x78, 0x70, 0x60, 0x88, 0x96, 0x45}}, 
    {.type = 0, .addr = {0x78, 0x70, 0x60, 0x88, 0x96, 0x46}}, 
    {.type = 0, .addr = {0x78, 0x70, 0x60, 0x88, 0x96, 0x47}}, 
    {.type = 0, .addr = {0x78, 0x70, 0x60, 0x88, 0x96, 0x48}}, 
    };
/*
door：0
water: 1
red: 2
sound: 3
*/
ssapc_write_param_t g_sle_uart_send_param = { 0 };
// uint16_t g_sle_uart_conn_id = 0;
uint8_t g_client_id = 0;
static uint8_t g_at_pre_char = 0;
static uint32_t g_at_uart_recv_cnt = 0;
#define SLE_UART_TRANSFER_SIZE              256
static uint8_t g_app_uart_rx_buff[SLE_UART_TRANSFER_SIZE] = { 0 };



typedef struct {
    uint8_t index;                         /*!< @if Eng SLE device address type { @ref @ref SleAddrType }
                                               @else   SLE设备地址状态 { @ref @ref SleAddrType } @endif */
    uint8_t conn_id ;                      /*!< @if Eng SLE device address
                                               @else   SLE设备地址 @endif */
    unsigned char deviceReadBuff[16];

    unsigned char devicewriteBuff[16];
} device_param;
/*
door：0
water: 1
red: 2
sound: 3
*/
#define device_door 0
#define device_water 1
#define device_red 2
#define device_sound 3

#define SLE_UART_CLIENT_MAX_CON         8
static device_param g_sle_uart_conn_id[SLE_UART_CLIENT_MAX_CON] = { 
    {.conn_id = -1},
    {.conn_id = -1},
    {.conn_id = -1},
    {.conn_id = -1},
    {.conn_id = -1},
    {.conn_id = -1},
    {.conn_id = -1},
    {.conn_id = -1},
};

uint16_t g_sle_uart_conn_num = 0;

// ******************4G上云部分
#define UART_NUM 1
static void L610_open(void);
static void L610_close(void);
static void L610_MQTTUSER(char *Username, char *Password,char *ClientIDStr);
static void L610_MQTTSub(uint8_t *topic);
static void L610_MQTTPub(uint8_t *topic,uint8_t *msg);
#define MQTT_CMD_MAX_SIZE 100
uint8_t mqtt_cmd[MQTT_CMD_MAX_SIZE];
static void process_data(const char *data,uint16_t length) ;
int parse_value(const char *json, const char *key, int *value);
void send_data(int device_index, int value);
const char* getLifeState(int index);
const char* getdeviceState(int index);
//sub

char *SubTopic[device_my] = {
    "doorsub_request1",
    "watersub_request",
    "redsub_request",
    "soundsub_request"
};
char *PubTopic[8] = {
    "doorpub_state",
    "waterpub_state",
    "redpub_state",
    "soundpub_state",
    "doorpub_life",
    "waterpub_life",
    "redpub_life",
    "soundpub_life"
};

//***************wifi上云部分

static void WIFI_activate(void);
static void WIFI_MQTTconn(void);

// #define Max_MQTTconn 5
// 定义一个宏，用于标识SSID。请根据实际情况修改
#define PARAM_HOTSPOT_SSID "朱迪"

// 定义一个宏，用于标识密码。请根据实际情况修改
#define PARAM_HOTSPOT_PSK "zxd12345"

// 定义一个宏，用于标识MQTT服务器IP地址。请根据实际情况修改
#define PARAM_SERVER_ADDR "120.237.20.252"

// 定义一个宏，用于标识MQTT服务器端口
#define PARAM_SERVER_PORT "50083"

//定义一个变量，定义WIFI的连接情况
int WIFI_conn_state;



//**********************线程中的信号量定义
osSemaphoreId_t sem;

//***********************上下云队列
typedef enum {
    CLOUD_MSG_TYPE_PUBLISH,
    CLOUD_MSG_TYPE_SUBSCRIBE,
    CLOUD_LIFE_TYPE_PUBLISH
    //加上WIFI的情况
} CloudMsgType;

typedef struct {
    CloudMsgType type;
    char *topic;
    uint8_t message[50];
    int device_id;
    char data;
} CloudMessage;

//上下云队列
osMessageQueueId_t cloudMessageQueue;






uint16_t get_g_sle_uart_conn_id(uint8_t i)
{
    return g_sle_uart_conn_id[i].conn_id;
}
uint16_t get_g_sle_uart_index(uint8_t i)
{
    return g_sle_uart_conn_id[i].index;
}

ssapc_write_param_t *get_g_sle_uart_send_param(void)
{
    return &g_sle_uart_send_param; 
}

/*
函数名称：static void uart_rx_callback(const void *buffer, uint16_t length, bool error)
函数作用：对4G模块的接受数据回调
*/
static void uart_rx_callback(const void *buffer, uint16_t length, bool error)
{
    if (error) {
        osal_printk("UART reception error.\r\n");
        return; 
    }
    process_data(buffer,length);
}
static uart_buffer_config_t g_app_uart_buffer_config = {
    .rx_buffer = g_app_uart_rx_buff,
    .rx_buffer_size = SLE_UART_TRANSFER_SIZE
};
void uart1_config(void){
    uapi_uart_deinit(1);
     IotUartAttribute g_uart_cfg = {115200, 8, 1, IOT_UART_PARITY_NONE, 100, 100, 0}; 
      IoTUartInit(1, &g_uart_cfg); 
    (void)uapi_uart_register_rx_callback(1, UART_RX_CONDITION_FULL_OR_IDLE,
                                        64, uart_rx_callback);
}

/*
函数名称：process_data(const char *data, uint16_t length)
函数作用：对接受到的4G数据进行解析处理，对应不同的键值对下发给不同的子设备
*/
void process_data(const char *data, uint16_t length) {
    char buffer[200];
    memset(buffer,0,sizeof(buffer));
    memcpy(buffer, data, length);
    printf("%u",length);
    buffer[length] = '\0';  // 确保字符串以空字符结尾
    printf("%s",buffer);
    const char *msg_start = strstr(buffer, "+MQTTMSG: ");
    if (msg_start) {
        const char *json_start = strchr(msg_start, '{');
        if (json_start) {
            int value;// 尝试解析不同的键
            if (parse_value(json_start, "\"door\":", &value)) {
                send_data(0,value);
            } else if (parse_value(json_start, "\"water\":", &value)) {
                send_data(1,value);
            } else if (parse_value(json_start, "\"red\":", &value)) {
                send_data(2,value);
            } else if (parse_value(json_start, "\"sound\":", &value)) {
                send_data(3,value);
            }
        }
    }
    memset(buffer,0,sizeof(buffer));
}

int parse_value(const char *json, const char *key, int *value) {
    const char *p = strstr(json, key);
    if (p) {
        p += strlen(key);  // 移动到键值对的值部分
        char *end = strchr(p, ',');// 假设值是一个整数，并且后面跟着逗号或结束大括号
        if (!end) {
            end = strchr(p, '}');
        }
        if (end) {
            *value = atoi(p);
            return 1;  // 解析成功
        }
    }
    return 0;  // 解析失败
}

void send_data(int device_index, int value) {
    printf("Sending data to device %d with value %d\n", device_index, value);
    uint8_t message_send[64];
    snprintf(message_send, sizeof(message_send), "%d%d end", device_index, value);
    printf("\n%s\n",message_send);
    uart_sle_client_send_data(device_index, (uint8_t*)message_send, strlen(message_send) + 1);
    printf("\nsend ID is %d\n",g_sle_uart_conn_id[device_index].conn_id );
}

/*
函数模块名称：sle_uart_start_scan(void)，sle_uart_client_sample_sle_enable_cbk(errcode_t status)，sle_uart_client_sample_seek_enable_cbk(errcode_t status)，sle_uart_client_sample_seek_result_info_cbk(sle_seek_result_info_t *seek_result_data)
函数模块作用：广播状态的各类状态阶段回调函数
*/
void sle_uart_start_scan(void)
{
    SleSeekParam param = { 0 };
    param.ownaddrtype = 0;
    param.filterduplicates = 0;
    param.seekfilterpolicy = 0;
    param.seekphys = 1;
    param.seekType[0] = 1;
    param.seekInterval[0] = SLE_SEEK_INTERVAL_DEFAULT;
    param.seekWindow[0] = SLE_SEEK_WINDOW_DEFAULT;
    SleSetSeekParam(&param);
    SleStartSeek();
}

static void sle_uart_client_sample_sle_enable_cbk(errcode_t status)
{
    if (status != 0) {
        osal_printk("%s sle_uart_client_sample_sle_enable_cbk,status error\r\n", SLE_UART_CLIENT_LOG);
    } else {
        osal_msleep(SLE_UART_TASK_DELAY_MS);
        sle_uart_start_scan();
    }
}
static void sle_uart_client_sample_seek_enable_cbk(errcode_t status)
{
    if (status != 0) {
        osal_printk("%s sle_uart_client_sample_seek_enable_cbk,status error\r\n", SLE_UART_CLIENT_LOG);
    }
}
static void sle_uart_client_sample_seek_result_info_cbk(sle_seek_result_info_t *seek_result_data)
{
    // osal_printk("sle_sample_seek_result_info_cbk  [%02x,%02x,%02x,%02x,%02x,%02x]\n",
    //     seek_result_data->addr.addr[0], seek_result_data->addr.addr[1], seek_result_data->addr.addr[2],
    //     seek_result_data->addr.addr[3], seek_result_data->addr.addr[4], seek_result_data->addr.addr[5]);
    // osal_printk("sle_sample_seek_result_info_cbk %s\r\n", seek_result_data->data);
    if (seek_result_data != NULL) {
        if(g_sle_uart_conn_num < SLE_UART_CLIENT_MAX_CON){
            if (strstr((const char *)seek_result_data->data, SLE_UART_SERVER_NAME) != NULL) {
                osal_printk("will connect dev\n");
                (void)memcpy_s(&g_sle_uart_remote_addr, sizeof(sle_addr_t), &seek_result_data->addr, sizeof(sle_addr_t));
                SleStopSeek();
            }
        }
    }
}
static void sle_uart_client_sample_seek_disable_cbk(errcode_t status)
{
    if (status != 0) {
        osal_printk("%s sle_uart_client_sample_seek_disable_cbk,status error = %x\r\n", SLE_UART_CLIENT_LOG, status);
    } else {
       SleConnectRemoteDevice(&g_sle_uart_remote_addr);
    }
}

static void sle_uart_client_sample_seek_cbk_register(void)
{
    g_sle_uart_seek_cbk.sle_enable_cb = sle_uart_client_sample_sle_enable_cbk;
     g_sle_uart_seek_cbk.seek_enable_cb = sle_uart_client_sample_seek_enable_cbk;
    g_sle_uart_seek_cbk.seek_result_cb = sle_uart_client_sample_seek_result_info_cbk;
     g_sle_uart_seek_cbk.seek_disable_cb = sle_uart_client_sample_seek_disable_cbk;
    sle_announce_seek_register_callbacks(&g_sle_uart_seek_cbk);
}




/*
函数名称：sle_uart_client_sample_connect_state_changed_cbk(uint16_t conn_id, const sle_addr_t *addr,
                                                             sle_acb_state_t conn_state, sle_pair_state_t pair_state,
                                                             sle_disc_reason_t disc_reason)
函数作用：每次连接一个设备，检查该设备的地址是否与所记录的地址库中的地址相同，相同的话即是本系统中的地址。一旦连接成功即
订阅相关的主题，可以接收到云平台在该主题下发的命令。
*/

static void sle_uart_client_sample_connect_state_changed_cbk(uint16_t conn_id, const SleAddr *addr,
    SleAcbStateType conn_state, SlePairStateType pair_state, SleDiscReasonType disc_reason)
{
    unused(pair_state);
    osal_printk("%s conn state changed disc_reason:0x%x\r\n", SLE_UART_CLIENT_LOG, disc_reason);

    // 处理连接状态变化
    if (conn_state == SLE_ACB_STATE_CONNECTED) {
        osal_printk("%s SLE_ACB_STATE_CONNECTED\r\n", SLE_UART_CLIENT_LOG);
        ssap_exchange_info_t info = {0};
        info.mtu_size = SLE_MTU_SIZE_DEFAULT;
        info.version = 1;
        ssapc_exchange_info_req(1, conn_id, &info);
        g_sle_uart_conn_num++;
    } else if (conn_state == SLE_ACB_STATE_NONE) {
        osal_printk("%s SLE_ACB_STATE_NONE\r\n", SLE_UART_CLIENT_LOG);
    } else if (conn_state == SLE_ACB_STATE_DISCONNECTED) {
        osal_printk("%s SLE_ACB_STATE_DISCONNECTED\r\n", SLE_UART_CLIENT_LOG);
        g_sle_uart_conn_num--;
        //printf("\n%d\n",g_sle_uart_conn_num);
        sle_uart_start_scan();
    } else {
        osal_printk("%s status error\r\n", SLE_UART_CLIENT_LOG);
    }

    for (int i = 0; i < 4; i++) {
        if (memcmp(addr->addr, device_addr_my[i].addr, OH_SLE_ADDR_LEN) == 0) {
            
            printf("\nmy ID is %d\n", g_sle_uart_conn_id[i].conn_id);
            CloudMessage Msg;
            // CloudMessage Msg_pub;
            if (conn_state == SLE_ACB_STATE_CONNECTED) {
                g_sle_uart_conn_id[i].index = 1;
                g_sle_uart_conn_id[i].conn_id = conn_id;
                //***添加对WIFI状态的判断
                // 订阅主题
                Msg.type = CLOUD_MSG_TYPE_SUBSCRIBE;
                Msg.topic = SubTopic[i];
                // Msg.device_id = i;
                osMessageQueuePut(cloudMessageQueue, &Msg, 0, osWaitForever);
                //发布上线包
                Msg.type = CLOUD_LIFE_TYPE_PUBLISH;
                Msg.topic = PubTopic[i + 4];
                Msg.device_id = i;
                Msg.data = '1';
                osMessageQueuePut(cloudMessageQueue, &Msg, 0, osWaitForever);
            } 
            else if (conn_state == SLE_ACB_STATE_DISCONNECTED) {
                g_sle_uart_conn_id[i].index = 0;
                g_sle_uart_conn_id[i].conn_id = -1;
                //发布下线包
                Msg.type = CLOUD_LIFE_TYPE_PUBLISH;
                Msg.topic = PubTopic[i + 4];
                Msg.device_id = i;
                Msg.data = '0';
                osMessageQueuePut(cloudMessageQueue, &Msg, 0, osWaitForever);
            }
        }
        printf("time1 : %d\n", g_sle_uart_conn_id[i].conn_id);
    }
    SleStartSeek();
}

static void sle_uart_client_sample_connect_cbk_register(void)
{
    g_sle_uart_connect_cbk.connectStateChangedCb = sle_uart_client_sample_connect_state_changed_cbk;
    SleConnectionRegisterCallbacks(&g_sle_uart_connect_cbk);
}
static void sle_uart_client_sample_exchange_info_cbk(uint8_t client_id, uint16_t conn_id, ssap_exchange_info_t *param,
                                                     errcode_t status)
{
    osal_printk("%s exchange_info_cbk,pair complete client id:%d status:%d\r\n",
                SLE_UART_CLIENT_LOG, client_id, status);
    osal_printk("%s exchange mtu, mtu size: %d, version: %d.\r\n", SLE_UART_CLIENT_LOG,
                param->mtu_size, param->version);
    ssapc_find_structure_param_t find_param = { 0 };
    find_param.type = 1;
    find_param.start_hdl = 1;
    find_param.end_hdl = 0xFFFF;
   int ret =  ssapc_find_structure(client_id, conn_id, &find_param);

   printf("ssapc_find_structure_errcode:%d\r\n",ret);
}

static void sle_uart_client_sample_find_structure_cbk(uint8_t client_id, uint16_t conn_id,
                                                      ssapc_find_service_result_t *service,
                                                      errcode_t status)
{
    osal_printk("%s find structure cbk client: %d conn_id:%d status: %d \r\n", SLE_UART_CLIENT_LOG,
                client_id, conn_id, status);
    osal_printk("%s find structure start_hdl:[0x%02x], end_hdl:[0x%02x], uuid len:%d\r\n", SLE_UART_CLIENT_LOG,
                service->start_hdl, service->end_hdl, service->uuid.len);
    g_sle_uart_find_service_result.start_hdl = service->start_hdl;
    g_sle_uart_find_service_result.end_hdl = service->end_hdl;
    memcpy_s(&g_sle_uart_find_service_result.uuid, sizeof(sle_uuid_t), &service->uuid, sizeof(sle_uuid_t));


}

static void sle_uart_client_sample_find_property_cbk(uint8_t client_id, uint16_t conn_id,
                                                     ssapc_find_property_result_t *property, errcode_t status)
{
    osal_printk("%s sle_uart_client_sample_find_property_cbk, client id: %d, conn id: %d, operate ind: %d, "
                "descriptors count: %d status:%d property->handle %d\r\n", SLE_UART_CLIENT_LOG,
                client_id, conn_id, property->operate_indication,
                property->descriptors_count, status, property->handle);
    g_sle_uart_send_param.handle = property->handle;
    g_sle_uart_send_param.type = SSAP_PROPERTY_TYPE_VALUE;
}

static void sle_uart_client_sample_find_structure_cmp_cbk(uint8_t client_id, uint16_t conn_id,
                                                          ssapc_find_structure_result_t *structure_result,
                                                          errcode_t status)
{
    unused(conn_id);


    osal_printk("%s sle_uart_client_sample_find_structure_cmp_cbk,client id:%d status:%d type:%d uuid len:%d \r\n",
                SLE_UART_CLIENT_LOG, client_id, status, structure_result->type, structure_result->uuid.len);
}

static void sle_uart_client_sample_write_cfm_cb(uint8_t client_id, uint16_t conn_id,
                                                ssapc_write_result_t *write_result, errcode_t status)
{
    osal_printk("%s sle_uart_client_sample_write_cfm_cb, conn_id:%d client id:%d status:%d handle:%02x type:%02x\r\n",
                SLE_UART_CLIENT_LOG, conn_id, client_id, status, write_result->handle, write_result->type);
}

static void sle_uart_client_sample_ssapc_cbk_register(ssapc_notification_callback notification_cb,
                                                      ssapc_indication_callback indication_cb)
{
    g_sle_uart_ssapc_cbk.exchange_info_cb = sle_uart_client_sample_exchange_info_cbk;
    g_sle_uart_ssapc_cbk.find_structure_cb = sle_uart_client_sample_find_structure_cbk;
    g_sle_uart_ssapc_cbk.ssapc_find_property_cbk = sle_uart_client_sample_find_property_cbk;
    g_sle_uart_ssapc_cbk.find_structure_cmp_cb = sle_uart_client_sample_find_structure_cmp_cbk;
    g_sle_uart_ssapc_cbk.write_cfm_cb = sle_uart_client_sample_write_cfm_cb;
    g_sle_uart_ssapc_cbk.notification_cb = notification_cb;
    g_sle_uart_ssapc_cbk.indication_cb = indication_cb;
    ssapc_register_callbacks(&g_sle_uart_ssapc_cbk);
}


static errcode_t sle_uuid_client_register(void)
{
    errcode_t ret;
    SleUuid app_uuid = {0};

    printf("[uuid client] ssapc_register_client \r\n");
    app_uuid.len = sizeof(g_sle_uuid_app_uuid);
    if (memcpy_s(app_uuid.uuid, app_uuid.len, g_sle_uuid_app_uuid, sizeof(g_sle_uuid_app_uuid)) != EOK) {
        return ERRCODE_SLE_FAIL;
    }
    ret = SsapcRegisterClient(&app_uuid, &g_client_id);

    return ret;
}


/*
函数名称：sle_uart_client_send_report_by_handle(uint8_t i, const uint8_t *data, uint8_t len)
函数作用：对连接的设备标好conn_id，确保发送数据是按照conn_id进行标识发送的。
*/
errcode_t sle_uart_client_send_report_by_handle(uint8_t i, const uint8_t *data, uint8_t len)
{
    // if (i >= SLE_UART_CLIENT_MAX_CON || g_sle_uart_conn_id[i].index == 65535) {
    //     return ERRCODE_SLE_FAIL;
    // }
    ssapc_write_param_t param = {0};
    uint8_t receive_buf[0x100] = {0}; /* max receive length. */
    param.handle = g_sle_uart_find_service_result.start_hdl;
    param.type = SSAP_PROPERTY_TYPE_VALUE;
    param.data = receive_buf;
    param.data_len = len;
    if (memcpy_s(param.data, sizeof(receive_buf), data, len) != EOK) {
        return ERRCODE_SLE_FAIL;
    }
    errcode_t ret = SsapWriteReq(g_client_id, g_sle_uart_conn_id[i].conn_id, &param);
    return ret;
}

int uart_sle_client_send_data(uint8_t index, const uint8_t *data, uint8_t length) {
    int ret; 
    ret = sle_uart_client_send_report_by_handle(index,data, length);  
    return ret;
}


/*
函数名称：ssapc_notification_callbacks(uint8_t client_id, uint16_t conn_id, ssapc_handle_value_t *data,
    errcode_t status)
函数作用：将从设备收到的数据转化成固定格式，并且根据标识符进行不同设备不同主题的上云。加了点小逻辑判断，一旦门开了就向语音
模块下发 门开了 的命令。
*/
void ssapc_notification_callbacks(uint8_t client_id, uint16_t conn_id, ssapc_handle_value_t *data,
    errcode_t status){
        (void)client_id;
        (void)conn_id;
        (void)status;
        data->data[data->data_len -1] = '\0';
        printf("server_send_data: %s\n", data->data);
        if (data != NULL && data->data_len > 2)
        {
            if (data->data_len > 1) {
                //***在上云信息前加上对WIFI状态的识别
                if(data->data[0] == '0' && g_sle_uart_conn_id[device_door].index == 1)
                {
                    if(data->data[1] == '0')send_data(3,0);
                    else if(data->data[1] == '1')send_data(3,1);
                    CloudMessage publishMsg;
                    publishMsg.type = CLOUD_MSG_TYPE_PUBLISH;
                    publishMsg.topic = PubTopic[0];
                    publishMsg.device_id = device_door;
                    publishMsg.data = data->data[1];
                    osMessageQueuePut(cloudMessageQueue, &publishMsg, 0, osWaitForever);
                }else if(data->data[0] == '1' && g_sle_uart_conn_id[device_water].index == 1)
                {
                    if(data->data[1] == '1')send_data(3,9);
                    CloudMessage publishMsg;
                    publishMsg.type = CLOUD_MSG_TYPE_PUBLISH;
                    publishMsg.topic = PubTopic[1];
                    // snprintf(publishMsg.message, sizeof(publishMsg.message), "\"{\\22device_water\\22:%c}\"", data->data[1]);
                    publishMsg.device_id = device_water;
                    publishMsg.data = data->data[1];
                    osMessageQueuePut(cloudMessageQueue, &publishMsg, 0, osWaitForever);
                }else if(data->data[0] == '2' && g_sle_uart_conn_id[device_red].index == 1)
                {
                    CloudMessage publishMsg;
                    publishMsg.type = CLOUD_MSG_TYPE_PUBLISH;
                    publishMsg.topic = PubTopic[2];
                    // snprintf(publishMsg.message, sizeof(publishMsg.message), "\"{\\22device_red\\22:%c}\"", data->data[1]);
                    publishMsg.device_id = device_red;
                    publishMsg.data = data->data[1];
                    osMessageQueuePut(cloudMessageQueue, &publishMsg, 0, osWaitForever);
                }else if(data->data[0] == '3' && g_sle_uart_conn_id[device_sound].index == 1)
                {
                    CloudMessage publishMsg;
                    publishMsg.type = CLOUD_MSG_TYPE_PUBLISH;
                    publishMsg.topic = PubTopic[3];
                    // snprintf(publishMsg.message, sizeof(publishMsg.message), "\"{\\22device_sound\\22:%c}\"", data->data[1]);
                    publishMsg.device_id = device_sound;
                    publishMsg.data = data->data[1];
                    osMessageQueuePut(cloudMessageQueue, &publishMsg, 0, osWaitForever);
                }
        }else{
            printf("Data is NULL or data_len is too short.\r\n");
        }
    }
}

// 获取生命状态的字符串
const char* getLifeState(int index) {
    const char* states[] = {"door", "water", "red", "sound"};
    return states[index];
}

// 获取设备数据的字符串
const char* getdeviceState(int index) {
    const char* states[] = {"device_door", "device_water", "device_red", "device_sound"};
    return states[index];
}

/*
函数名称： ssapc_indication_callbacks(uint8_t client_id, uint16_t conn_id, ssapc_handle_value_t *data,
    errcode_t status)
函数作用：发送数据至设备的回调
*/
void ssapc_indication_callbacks(uint8_t client_id, uint16_t conn_id, ssapc_handle_value_t *data,
    errcode_t status){
(void)client_id;
        (void)conn_id;
         (void)data;
        (void)status;
    }



/*
函数名称：sle_uart_client_init()
函数作用：初始化客户端，配置其地址与各个回调函数
*/
void sle_uart_client_init()
{
    uint8_t local_addr[SLE_ADDR_LEN] = { 0x13, 0x67,0x5c, 0x07, 0x00, 0x51 };//0x04-->0x07
    SleAddr local_address;
    local_address.type = 0;
    (void)memcpy_s(local_address.addr, SLE_ADDR_LEN, local_addr, SLE_ADDR_LEN);
    sle_uuid_client_register();
    sle_uart_client_sample_seek_cbk_register();
    sle_uart_client_sample_connect_cbk_register();
    sle_uart_client_sample_ssapc_cbk_register(ssapc_notification_callbacks, ssapc_indication_callbacks);
    EnableSle();
	SleSetLocalAddr(&local_address);
    
}


/*
函数模块名称： L610_activate()，L610_MQTTSub(uint8_t *topic)，L610_MQTTPub(uint8_t *topic,uint8_t *msg)
函数作用：入网上云，发布，订阅
*/
static void L610_open()
{
    uint8_t  msg1[] = "ATE0\r\n";
    uint8_t  msg8[] = "AT+MIPCALL=1\r\n";
    uint8_t  msg14[] = "AT+MQTTOPEN=1,\"120.237.20.252\",50083,0,60\r\n";
    IoTUartWrite(UART_NUM, msg1, sizeof(msg1));
    usleep(1000000);   
    IoTUartWrite(UART_NUM, msg8, sizeof(msg8));
    usleep(1000000);
    IoTUartWrite(UART_NUM, msg14, sizeof(msg14));
    usleep(1000000);
}
static void L610_close()
{
    uint8_t msgCALL0[] = "AT+MIPCALL=0\r\n";
    uint8_t msgBREAKM[] = "AT+MQTTCLOSE=1\r\n";
    uint8_t msgBREAKM_door[] = "AT+MQTTUNSUB=1,\"doorsub_request1\"\r\n";
    uint8_t msgBREAKM_red[] = "AT+MQTTUNSUB=1,\"redsub_request\"\r\n";
    uint8_t msgBREAKM_sound[] = "AT+MQTTUNSUB=1,\"soundsub_request\"\r\n";
    IoTUartWrite(UART_NUM, msgBREAKM_door, sizeof(msgBREAKM_door));
    usleep(500000);
    IoTUartWrite(UART_NUM, msgBREAKM_red, sizeof(msgBREAKM_red));
    usleep(500000);
    IoTUartWrite(UART_NUM, msgBREAKM_sound, sizeof(msgBREAKM_sound));
    usleep(500000);
    IoTUartWrite(UART_NUM, msgBREAKM, sizeof(msgBREAKM));
    usleep(500000);
    IoTUartWrite(UART_NUM, msgCALL0, sizeof(msgCALL0));
    usleep(500000);
}
static void L610_devicelife_close()
{
    uint8_t msglifeclose_door[] = "AT+MQTTPUB=1,\"doorpub_life\",1,0,\"{\\22life_door\\22:0}\"\r\n";
    uint8_t msglifewater_water[] = "AT+MQTTPUB=1,\"waterpub_life\",1,0,\"{\\22life_water\\22:0}\"\r\n";
    uint8_t msglifeclose_red[] = "AT+MQTTPUB=1,\"redpub_life\",1,0,\"{\\22life_red\\22:0}\"\r\n";
    uint8_t msglifeclose_sound[] = "AT+MQTTPUB=1,\"soundpub_life\",1,0,\"{\\22life_sound\\22:0}\"\r\n";
    IoTUartWrite(UART_NUM, msglifeclose_door, sizeof(msglifeclose_door));
    usleep(500000);
    IoTUartWrite(UART_NUM, msglifewater_water, sizeof(msglifewater_water));
    usleep(500000);
    IoTUartWrite(UART_NUM, msglifeclose_red, sizeof(msglifeclose_red));
    usleep(500000);
    IoTUartWrite(UART_NUM, msglifeclose_sound, sizeof(msglifeclose_sound));
    usleep(500000);
}

static void L610_MQTTSub(uint8_t *topic) {
    // MQTT订阅: AT+MQTTSUB=1,"topic",1
    memset(mqtt_cmd, 0, sizeof(mqtt_cmd)); // 清空命令
    snprintf(mqtt_cmd, sizeof(mqtt_cmd), "AT+MQTTSUB=1,\"%s\",1\r\n", topic); 
    IoTUartWrite(UART_NUM, mqtt_cmd, strlen(mqtt_cmd));
}

static void L610_MQTTPub(uint8_t *topic, uint8_t *msg) {
    // MQTT发布: AT+MQTTPUB=1,"topic",1,0,"msg"
    memset(mqtt_cmd, 0, sizeof(mqtt_cmd)); 
    snprintf(mqtt_cmd, sizeof(mqtt_cmd), "AT+MQTTPUB=1,\"%s\",1,0,%s\r\n", topic, msg); 
    IoTUartWrite(UART_NUM, mqtt_cmd, strlen(mqtt_cmd));
}


/*
函数模块名称： WIFI_MQTT_init(int state), Cloud_resub(void), Cloud_resub(void), MQTT_reconn(void)
函数作用：初始化wifi，连接MQTT，发布MQTT心跳包，订阅上线设备主题
*/
static void WIFI_MQTT_init(int state)
{
    if(state == 1)
    {
        printf("STA try enable.\r\n");
        while (wifi_sta_enable() != ERRCODE_SUCC)
        {
            printf("STA enable fail, retry...\r\n");
            osal_msleep(100);
        }
    }

    if (ConnectToHotspot(PARAM_HOTSPOT_SSID, PARAM_HOTSPOT_PSK) != 0)
    {
        // 连接到热点失败
        printf("Connect to AP failed\n"); // 输出错误信息
    }

    // 等待1s，否则会出现TCP连接失败
    osDelay(100);

    // 初始化并启动MQTT任务，连接MQTT服务器
    if(state == 1)
    {
        MqttTaskInit();                                                     // 初始化并启动MQTT任务
    }
    MQTT_reconn();
}

void Cloud_resub(void)
{
    CloudMessage Msg;
    for(int i = 0; i < 5; i++)
    {
        if(g_sle_uart_conn_id[i].index)
        {
            Msg.type = CLOUD_MSG_TYPE_SUBSCRIBE;
            Msg.topic = SubTopic[i];
            // Msg.device_id = i;
            osMessageQueuePut(cloudMessageQueue, &Msg, 0, osWaitForever);
        }
    }
}

void MQTT_reconn(void)
{
    const char *host = PARAM_SERVER_ADDR;                               // MQTT服务器IP地址
    unsigned short port = atoi(PARAM_SERVER_PORT);                      // MQTT服务器端口
    const char *clientId = "NearLink0001";                              // MQTT客户端ID
    const char *username = NULL;                                        // MQTT服务器用户名
    const char *password = NULL;                                        // MQTT服务器密码
    int time = 5;
    while(time--)
    {
        if (MqttTaskConnect(host, port, clientId, username, password) == 0) // 连接MQTT服务器
        {
            Cloud_resub();
            break;
        }
        osal_msleep(500);
    }
}

/*
函数名称：SleTask(char* arg)
函数作用：初始化串口，星闪和4G模组，设置信号量
*/
static void SleTask(char* arg)
{
    (void)arg;
    usleep(1000000);
    /*串口初始化*/
    uart1_config();

    /*星闪连接初始化*/
    sle_uart_client_init();


    /*4G+MQTT初始化*/
    // 等待1s，否则会出现TCP连接失败
    osDelay(100);
    L610_open();
    L610_devicelife_close();
    
    osSemaphoreRelease(sem);
}


/*
函数名称：CloudMessageHandlerTask(void *arg)
函数作用：把发布订阅的内容放在队列中，循环读取处理队列中的内容
*/
static void CloudMessage_4GHandlerTask(void *arg) {
    (void)arg;
    // osSemaphoreAcquire(sem, osWaitForever);
    usleep(2000000);
    CloudMessage msg;
    while (1) {
        if (osMessageQueueGet(cloudMessageQueue, &msg, NULL, 100) == osOK) {
            if(WIFI_conn_state == 0)
            {
                switch (msg.type) {
                    case CLOUD_MSG_TYPE_PUBLISH:
                        snprintf(msg.message, sizeof(msg.message), "\"{\\22%s\\22:%c}\"", getdeviceState(msg.device_id), msg.data);
                        L610_MQTTPub(msg.topic, msg.message);
                        break;
                    case CLOUD_MSG_TYPE_SUBSCRIBE:
                        printf("\n%d\n",WIFI_conn_state);
                        L610_MQTTSub(msg.topic);
                        break;
                    case CLOUD_LIFE_TYPE_PUBLISH:
                        snprintf(msg.message, sizeof(msg.message), "\"{\\22life_%s\\22:%c}\"", getLifeState(msg.device_id), msg.data);
                        L610_MQTTPub(msg.topic, msg.message);
                        break;
                    default:
                        break;
                }
            }
            else if(WIFI_conn_state == 1)
            {
                switch (msg.type) {
                    case CLOUD_MSG_TYPE_PUBLISH:
                        snprintf(msg.message, sizeof(msg.message), "{\"%s\":%c}", getdeviceState(msg.device_id), msg.data);
                        MqttTaskPublish(msg.topic, msg.message);
                        break;
                    case CLOUD_MSG_TYPE_SUBSCRIBE:
                        printf("\n%d\n",WIFI_conn_state);
                        MqttTaskSubscribe(msg.topic);
                        break;
                    case CLOUD_LIFE_TYPE_PUBLISH:
                        snprintf(msg.message, sizeof(msg.message), "{\"life_%s\":%c}", getLifeState(msg.device_id), msg.data);
                        MqttTaskPublish(msg.topic, msg.message);
                        break;
                    default:
                        break;
                }
            }
        }
        usleep(500000);
    }
}

/*
函数名称：WIFIlifeTask(void *arg)
函数作用：判断WIFI是否连接，连接的话则发送心跳包，保证WIFIMQTT连接；如果不是连接状态，则进行WIFI扫描，确保热点打开能连接上对应的WIFI。
保留订阅主题，每一次切换WIFI或者4G就进行一次连接设备的主题订阅。
*/
static void WIFIlifeTask(void *arg)
{
    (void)arg;
    osSemaphoreAcquire(sem, osWaitForever);
    char *ptopic = "net_state";                                //心跳包 主题                          
    char *payload_WIFI = "{\"life\":1}";                                     //心跳包 消息内容
    char *payload_4G = "\"{\\22life\\22:0}\"";  
    L610_MQTTPub(ptopic, payload_4G);
    osDelay(50);
    Cloud_resub();
    WIFI_MQTT_init(1);
    int rem = 0;
    while(1)
    {
        if(!MqttTaskPublish(ptopic, payload_WIFI))
        {
            WIFI_conn_state = 1;
            printf("\n WIFI _____________ ok   WIFI_state______%d",WIFI_conn_state);
            //逻辑判断状态wifi是否改变
            if(WIFI_conn_state - rem)L610_close();
            rem = WIFI_conn_state;
            osDelay(400);
        }
        else
        {
            osDelay(100);
            MQTT_reconn();
            if(!MqttTaskPublish(ptopic, payload_WIFI))
            {
                continue;
            }
            WIFI_conn_state = 0;
            rem = WIFI_conn_state;
            L610_open();
            L610_MQTTPub(ptopic, payload_4G);
            osDelay(50);
            Cloud_resub();
            WIFI_MQTT_init(0);
            WIFI_conn_state = 1;
            Cloud_resub();
        }
    }
}


/*
函数名称：SleClientExample(void)
函数作用：分配线程优先级等
*/
static void SleClientExample(void)
{
    sem = osSemaphoreNew(2, 0, NULL);
    cloudMessageQueue = osMessageQueueNew(10, sizeof(CloudMessage), NULL);

    //线程1（初始化）
    osThreadAttr_t attr;
    attr.name = "SleTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 1024 * 10;
    attr.priority = 23;

    if (osThreadNew(SleTask, NULL, &attr) == NULL) {
       printf("[SleExample] Falied to create SleTask!\n");
    }else printf("[SleExample]  create SleTask successfully !\n");

    //线程2（4G上下云管理）
    osThreadAttr_t attr_4Ghandler;
    attr_4Ghandler.name = "CloudMessage_4GHandlerTask";
    attr_4Ghandler.attr_bits = 0U;
    attr_4Ghandler.cb_mem = NULL;
    attr_4Ghandler.cb_size = 0U;
    attr_4Ghandler.stack_mem = NULL;
    attr_4Ghandler.stack_size = 1024 * 10;
    attr_4Ghandler.priority = 20;

    if (osThreadNew(CloudMessage_4GHandlerTask, NULL, &attr_4Ghandler) == NULL) {
        printf("Failed to create CloudMessage_4GHandlerTask!\n");
    } else {
        printf("Created CloudMessage_4GHandlerTask successfully !\n");
    }


    //线程3（WIFI心跳包）
    osThreadAttr_t attr_WIFIlife;
    attr_WIFIlife.name = "WIFIlifeTask";
    attr_WIFIlife.attr_bits = 0U;
    attr_WIFIlife.cb_mem = NULL;
    attr_WIFIlife.cb_size = 0U;
    attr_WIFIlife.stack_mem = NULL;
    attr_WIFIlife.stack_size = 1024 * 10;
    attr_WIFIlife.priority = osPriorityNormal;

    if (osThreadNew(WIFIlifeTask, NULL, &attr_WIFIlife) == NULL)
    {
        printf("[mqttDemoEntry] Falied to create mqttDemoTask!\n");
    }
}


SYS_RUN(SleClientExample);